package com.cras.webcam.http.handler;

import android.util.Log;

import com.cras.webcam.http.ChannelHandler;
import com.cras.webcam.http.HttpRequest;
import com.cras.webcam.http.HttpResponse;
import com.cras.webcam.http.HttpVersion;
import com.cras.webcam.http.exception.HttpRequestExcecption;
import com.cras.webcam.http.handler.codec.HttpRequestDecoder;
import com.cras.webcam.http.servlet.ServletDispacther;

import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;

/**
 * 负责接收http请求和发送http响应
 * @author cras
 *
 */
public class RequestHandler implements ChannelHandler {
	private static final String LOG_TAG = RequestHandler.class.getName();
	private HttpRequestDecoder requestDecoder;
	private HandlerContext ctx;
	private HttpRequest request = null;
	private HttpResponse response = null;
	private boolean sent=false;//是否已发送response

	
	public RequestHandler(HandlerContext ctx) throws Exception{
		if(null == ctx){
			throw new Exception("ChannelIo cannot be null");
		}
		this.ctx = ctx;
		this.requestDecoder = new HttpRequestDecoder(4096, 8192, 8192);
	}
	
	@Override
	public void handle(SelectionKey key) {
		Log.i(LOG_TAG,"[request handling]");
		if(key.isReadable()){// 判断是否有数据发送过来
			//recive
			try {
				if(hasRecicved()){
					Log.i(LOG_TAG,"[prepared to parse request...]");
					request = (HttpRequest)requestDecoder.channelRead(ctx,ctx.getReadBuffer());
					
					//deliver the request to backend handler
					//todo
					try {
						ServletDispacther.dispacth(request, response);
					}catch (HttpRequestExcecption excecption){
						Log.e(LOG_TAG,excecption.getMessage());
					}
					//prepare to build response
					response = new HttpResponse(HttpVersion.HTTP_1_1, ByteBuffer.allocate(0));
					//prepare to send response
					key.channel().register(key.selector(), SelectionKey.OP_WRITE,this);
				}
			} catch (Exception e) {
				// TODO: handle exception
				close();
				key.cancel();
				Log.e(LOG_TAG,"request handle process ",e);
			}
		}
		else if(key.isValid() && key.isWritable()){
			//send
			send();
		}
	}
	
	private boolean hasRecicved(){
		try {
			int cnt = ctx.read();
			if(cnt > 0 || cnt == -1) {
				return true;
			}
			return false;
//			return cio.read() == -1 ? true : false;
		} catch (IOException e) {
			Log.e(LOG_TAG,"request hasRecicved ",e);
		}
		return false;
	}

	
	private void send(){
		try {
			if(!sent){
				ctx.write(response.content());
				sent = true;
				Log.i(LOG_TAG,"[response has sent...]");
			}
			close();
		} catch (IOException e) {
			Log.e(LOG_TAG,"request send ",e);
		}
		//response.send();
	}

	private void close(){
		try {
			ctx.close();
		} catch (IOException e) {
			Log.e(LOG_TAG,"request close ",e);
		}
		
	}
}
